package com.cmc.cloud.cmclink.doc.api.document;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cmc.cloud.cmclink.doc.api.document.emums.SiStatusEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.SiValidEnum;
import com.cmc.cloud.cmclink.doc.api.document.rep.BlnoPageRespDto;
import com.cmc.cloud.cmclink.doc.api.document.req.si.BlnoBaseInfoDto;
import com.cmc.cloud.cmclink.doc.api.document.req.si.BlnoInfoDto;
import com.cmc.cloud.cmclink.doc.api.document.req.si.BlnoVslvoyBaseDto;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.BlnoCntrErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.BlnoErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.SpecialCargoApplyErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.entity.BlnoCntrDO;
import com.cmc.cloud.cmclink.doc.entity.BlnoDO;
import com.cmc.cloud.cmclink.doc.entity.BlnoVslvoyDO;
import com.cmc.cloud.cmclink.doc.entity.ConfirmNoticeDO;
import com.cmc.cloud.cmclink.doc.mapper.BlnoCntrMapper;
import com.cmc.cloud.cmclink.doc.mapper.BlnoMapper;
import com.cmc.cloud.cmclink.doc.mapper.BlnoVslvoyMapper;
import com.cmc.cloud.cmclink.doc.mapper.ConfirmNoticeMapper;
import com.cmc.cloud.cmclink.doc.service.VgmService;
import com.cmc.cloud.cmclink.doc.service.si.BlnoService;
import com.cmc.cloud.cmclink.doc.service.si.ConfirmNoticeService;
import com.cmc.cloud.cmclink.doc.vo.blnovo.BlnoInfoVO;
import com.cmc.cloud.cmclink.doc.vo.vgm.VgmCreateReqVO;
import com.cmes.framework.common.exception.ServiceException;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.common.pojo.CommonResult;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * SI更正
 *
 * @author tanzhuliang
 * @date 2025/7/7
 */
@Slf4j
@RestController
@Valid
public class SiChangeApiImpl implements SiChangeApi {

    @Resource
    private BlnoService blnoService;

    @Resource
    private ConfirmNoticeService confirmNoticeService;

    @Resource
    private VgmService vgmService;

    @Resource
    private BlnoMapper blnoMapper;

    @Resource
    private BlnoCntrMapper blnoCntrMapper;

    @Resource
    private ConfirmNoticeMapper confirmNoticeMapper;
    @Autowired
    private BlnoVslvoyMapper blnoVslvoyMapper;


    @Override
    public CommonResult<Void> createSiChange(BlnoInfoDto blnoInfoDto) {
        BlnoInfoVO blnoInfo = BeanUtil.copyProperties(blnoInfoDto, BlnoInfoVO.class);
        //变更记录拼箱货校验
        blnoService.createSiChange(blnoInfo);
        //变更VGM信息
        if(CollectionUtils.isNotEmpty(blnoInfoDto.getVgmCreateReqDtos())){
            changeSiVgm(blnoInfo.getVgmCreateReqVos());
        }
        return CommonResult.success();
    }

    private void changeSiVgm(List<VgmCreateReqVO> vgmReq){

        vgmService.changeSiVgm(vgmReq);
    }

    @Override
    public CommonResult<Boolean> checkSiChange(Long id) {
        return CommonResult.success(blnoService.checkSiChange(id));
    }

    /**
     * 相同的船名航次下面不同的提单号下面有相同的箱号，那么这个箱号就是拼箱，不允许修改船期
     * @param id 提单主表id
     * @return
     */
    @Override
    public CommonResult<Boolean> checkVesselScheduleChange(Long id) {
        BlnoDO blno = blnoMapper.selectById(id);
        if (Objects.isNull(blno)) {
            throw ServiceExceptionUtil.exception(BlnoErrorCodeConstants.BLNO_NOT_EXISTS);
        }
        List<BlnoCntrDO> blnoCntrs = blnoCntrMapper.selectList(new LambdaQueryWrapperX<BlnoCntrDO>().eqIfPresent(BlnoCntrDO::getBlnoId, blno.getId()));
        if (CollectionUtils.isEmpty(blnoCntrs)) {
            return CommonResult.success(Boolean.TRUE);
        }
        Set<String> cntrNos = blnoCntrs.stream().map(BlnoCntrDO::getCntrNo).collect(Collectors.toSet());

        //查询同船名数据
        List<BlnoDO> blnoDos = blnoMapper.selectList(new LambdaQueryWrapper<BlnoDO>().eq(BlnoDO::getBkgVesselCode, blno.getBkgVesselCode())
                .eq(BlnoDO::getBkgVoyage, blno.getBkgVoyage()).ne(BlnoDO::getId, blno.getId())
                .eq(BlnoDO::getValid, SiValidEnum.VALID.getValue())
                .ne(BlnoDO::getSiStatus, SiStatusEnum.BookingDraft.getValue()).eq(BlnoDO::getPodBlFlag, true));
        if (CollectionUtils.isNotEmpty(blnoDos)) {
            List<Long> blnoIds = blnoDos.stream().map(BlnoDO::getId).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(blnoIds)) {
                return CommonResult.success(Boolean.TRUE);
            }
            List<BlnoCntrDO> blnoCntrList = blnoCntrMapper.selectList(new LambdaQueryWrapperX<BlnoCntrDO>().inIfPresent(BlnoCntrDO::getBlnoId, blnoIds));
            if (CollectionUtils.isEmpty(blnoCntrList)) {
                return CommonResult.success(Boolean.TRUE);
            }
            Set<String> cntrNoList = blnoCntrList.stream().map(BlnoCntrDO::getCntrNo).collect(Collectors.toSet());
            cntrNos.retainAll(cntrNoList);
            if (CollectionUtils.isNotEmpty(cntrNos)) {
                throw ServiceExceptionUtil.exception(BlnoCntrErrorCodeConstants.BLNO_CNTR_LCL_EXITSTS, String.join("|",cntrNos));
            }
        }
        return CommonResult.success(Boolean.TRUE);
    }

    @Override
    public CommonResult<Void> cancelNotice(Long id) {
        BlnoDO blnoDo = blnoMapper.selectById(id);
        if (blnoDo == null) {
            throw ServiceExceptionUtil.exception(BlnoErrorCodeConstants.BLNO_NOT_EXISTS);
        }
        BlnoDO newBlnoDo = blnoMapper.selectOne(new LambdaQueryWrapperX<BlnoDO>().eq(BlnoDO::getBlNo, blnoDo.getBlNo()).eq(BlnoDO::getValid, SiValidEnum.PENDING.getValue()).last("limit 1"));
        if (Objects.isNull(newBlnoDo)) {
            throw ServiceExceptionUtil.exception(BlnoErrorCodeConstants.BLNO_ERROR_NOTICE_EXISTED);
        }
        ConfirmNoticeDO confirmNotice = confirmNoticeMapper.selectOne(new LambdaQueryWrapperX<ConfirmNoticeDO>().eq(ConfirmNoticeDO::getBlnoId, newBlnoDo.getId()).last("limit 1"));
        if (Objects.isNull(confirmNotice)) {
            throw ServiceExceptionUtil.exception(BlnoErrorCodeConstants.BLNO_ERROR_NOTICE_EXISTED);
        }
        confirmNoticeService.cancelNotice(confirmNotice.getId());
        return CommonResult.success();
    }

    @Override
    public CommonResult<Void> createSiVesselChange(BlnoInfoDto blnoInfoDto) {
        // 校验是否拼箱货,是的话不允许更新船期
        checkVesselScheduleChange(blnoInfoDto.getBlnoBasInfoVO().getId());
        BlnoDO oldBlnoDO = blnoService.getBlno(blnoInfoDto.getBlnoBasInfoVO().getId());
        if(oldBlnoDO != null && !getBlShipperChangeFlag(oldBlnoDO, blnoInfoDto.getBlnoBasInfoVO())){
            // 船期没有修改那就ng
            throw ServiceExceptionUtil.exception(BlnoErrorCodeConstants.BLNO_NOT_CHANGE_VSLVOY_INFO);
        }
        BlnoInfoVO blnoInfo = BeanUtil.copyProperties(blnoInfoDto, BlnoInfoVO.class);
        blnoService.createSiChange(blnoInfo);
        return CommonResult.success();
    }

    @Override
    public CommonResult<List<BlnoVslvoyBaseDto>> getBlnoVolovy(Long blnoId) {
        List<BlnoVslvoyDO> blnoVslvoyList = blnoVslvoyMapper.selectList(new LambdaQueryWrapperX<BlnoVslvoyDO>().eqIfPresent(BlnoVslvoyDO::getBlnoId, blnoId));
        List<BlnoVslvoyBaseDto> blnoVslvoyBaseDtos = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(blnoVslvoyList)) {
            blnoVslvoyBaseDtos = BeanUtil.copyToList(blnoVslvoyList, BlnoVslvoyBaseDto.class);
        }
        return CommonResult.success(blnoVslvoyBaseDtos);
    }

    /**
     * 查看船期是否修改过
     * @param oldBlnoDO 旧的
     * @param newBlnoDO 新的
     * @return true:改过了 fasle:没改过
     */
    private boolean getBlShipperChangeFlag(BlnoDO oldBlnoDO, BlnoBaseInfoDto newBlnoDO) {
        if(!Objects.equals(oldBlnoDO.getPorCode(), newBlnoDO.getPorCode())
                || !Objects.equals(oldBlnoDO.getPolCode(), newBlnoDO.getPolCode())
                || !Objects.equals(oldBlnoDO.getPodCode(), newBlnoDO.getPodCode())
                || !Objects.equals(oldBlnoDO.getDelCode(), newBlnoDO.getDelCode())
                || !Objects.equals(oldBlnoDO.getBkgVoyage(), newBlnoDO.getBkgVoyage())
                || !Objects.equals(oldBlnoDO.getBkgVesselCode(), newBlnoDO.getBkgVesselCode())) {
            return true;
        }
        return false;
    }



}
